// 选课
// 在大学里每个学生，为了达到一定的学分，必须从很多课程里选择一些课程来学习
// 在课程里有些课程必须在某些课程之前学习，如高等数学总是在其它课程之前学习
// 现在有 N 门功课，每门课有个学分，每门课有一门或没有直接先修课
// 若课程 a 是课程 b 的先修课即只有学完了课程 a，才能学习课程 b
// 一个学生要从这些课程里选择 M 门课程学习
// 问他能获得的最大学分是多少
// 测试链接 : https://www.luogu.com.cn/problem/P2014
// 提交以下的code，可以直接通过

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 301;
int nums[MAXN];
vector<int> g[MAXN];
vector<vector<int>> dp[MAXN];
int n, m;

inline int read()
{
    char ch = getchar();
    int x = 0, f = 1;
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = 10 * x + ch - '0';
        ch = getchar();
    }
    return f * x;
}

// 当前来到i号节点为头的子树
// 只在i号节点、及其i号节点下方的前j棵子树上挑选节点
// 一共挑选k个节点，并且保证挑选的节点连成一片
// 返回最大的累加和
int f(int i, int j, int k)
{
    if(k == 0) return 0;
    if(j == 0 || k == 1) return nums[i];
    if(dp[i][j][k] != -1) return dp[i][j][k];
    int ans = f(i, j - 1, k); // 不考虑第 j 棵子树
    // 考虑第 j 棵子树，第 j 棵子树头节点 v 
    int v = g[i][j - 1];
    for(int s = 1; s < k; ++s)
    {
        ans = max(ans, f(i, j - 1, k - s) + f(v, g[v].size(), s));
    }
    dp[i][j][k] = ans;
    return ans; 
}

// 普通解法，邻接表建图 + 相对好懂的动态规划
// 几乎所有题解都是普通解法的思路，只不过优化了常数时间、做了空间压缩
// 但时间复杂度依然是O(n * 每个节点的孩子平均数量 * m的平方)
int compute()
{
    // 初始化 dp 表
    for(int i = 0; i <= n; ++i)
    {
        dp[i].resize(g[i].size() + 1, vector<int>(m + 1, -1));
    }
    return f(0, g[0].size(), m);
}

int main()
{
    n = read(), m = read() + 1;
    // 节点编号从0~n
    for(int i = 1, pre; i <= n; ++i)
    {
        pre = read(); // pre 是先修课
        g[pre].emplace_back(i); // i 是后修课
        nums[i] = read(); // 学分
    }
    printf("%d\n", compute());

    return 0;
}